<template>
    <div class="upload-img-box">
        <el-upload :disabled="status == 'details'"
            :class="{ 'avatar-uploader': true, 'is-disabled': status == 'details' }" :action="uploadUrl"
            list-type="picture-card" :file-list="fileList" :limit="limit" :before-upload="beforeUpload"
            :on-success="handleSuccess" :on-exceed="handleExceed" :auto-upload="autoUpload" :on-change="changeFile"
            :on-remove="handleRemove" :on-preview="handlePictureCardPreview">
            <el-icon>
                <Plus />
            </el-icon>
        </el-upload>
        <!-- 预览 -->
        <el-dialog :model-value="dialogVisible" :append-to-body="true">
            <img width="100%" :src="dialogImageUrl" />
        </el-dialog>
    </div>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import { ElMessage } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';
import type { UploadProps } from 'element-plus';
import type { fileInfo } from "./@types";

const emit = defineEmits(["update:value", "change", "upload-success", "upload-remove"]);

const props = defineProps({
    uploadUrl: {
        type: String,
        default: () => {
            return "#";
        },
    },
    value: {
        type: [Array, String],
        default: () => {
            return [];
        },
    },
    imgWidth: {
        type: String,
        default: () => {
            return "80px";
        },
    },
    imgHeight: {
        type: String,
        default: () => {
            return "80px";
        },
    },
    // 最大上传张数
    limit: {
        type: Number,
        default: () => {
            return 1;
        },
    },
    // 最大上传大小
    maxSize: {
        type: Number,
        default: () => {
            return 3;
        },
    },
    // 文件类型
    imgType: {
        type: String,
        default: () => {
            return "image/jpeg,image/png,image/gif";
        },
    },
    autoUpload: {
        type: Boolean,
        default: () => {
            return false
        }
    },
    status: {
        type: String,
        default: () => {
            return 'add'
        }
    },
    openUploadFun: {
        type: Boolean,
        default: () => {
            return false
        }
    },
    uploadFun: {
        type: Function,
        default: () => {
            return (fileInfo: fileInfo, success: Function) => {

            }
        }
    }
})

const fileList = ref<fileInfo[]>([]);
const dialogImageUrl = ref("");
const dialogVisible = ref(false);

const beforeUpload: UploadProps['beforeUpload'] = (file) => {
    let imgTypes = props.imgType.split(",");
    let index = imgTypes.indexOf(file.type);
    const isLt2M = file.size / 1024 / 1024 < props.maxSize;
    if (index == -1) {
        ElMessage.error("请上传正确的图片格式");
    }
    if (!isLt2M) {
        ElMessage.error(`上传图片大小不能超过 ${props.maxSize}MB!`);
    }
    return index != -1 && isLt2M;
}
// 上传成功
const handleSuccess: UploadProps['onSuccess'] = (res, file) => {
    let fileInfo: fileInfo = {
        name: file.name,
        path: res.path ? res.path : "",
        uploadUrl: res.url ? res.url : "",
        uid: file.uid,
        url: file.url,
        status: "success",
        fromItem: "upload-img",
        data: res,
        file: file,
    };
    fileList.value.push(fileInfo);
    emit("update:value", fileList.value);
    emit("upload-success", fileInfo);
    emit("change", fileList.value);
}
// 文件改变
const changeFile: UploadProps["onChange"] = (files) => {
    props.uploadFun(files, handleSuccess);
    if (props.autoUpload || props.openUploadFun) return;
    let fileInfo = {
        name: files.name,
        path: files.url,
        uploadUrl: files.url,
        uid: files.uid,
        url: files.url,
        status: "success",
        fromItem: "upload-img",
        data: files.raw,
        file: files.raw,
    };
    fileList.value.push(fileInfo);
    emit("update:value", fileList.value);
    emit("upload-success", fileInfo);
    emit("change", fileList.value);

}
// 超出限制
const handleExceed: UploadProps["onExceed"] = (files, fileList) => {
    ElMessage.warning(`当前上传图片数量已达上限${props.limit}张`);
}
// 预览
const handlePictureCardPreview: UploadProps['onPreview'] = (file) => {
    dialogImageUrl.value = file.url!;
    dialogVisible.value = true;
}
// 删除
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
    let index = fileList.value.findIndex(item => item.uid == uploadFile.uid);
    fileList.value.splice(index, 1);
    emit("change", fileList.value);
    emit("update:value", fileList.value);
    emit("upload-remove", fileList.value);
}

watch(() => props.value, (newValue) => {
    if(!newValue){
        fileList.value = [];
        return ;
    }
    if (typeof newValue == "string") {
        fileList.value = newValue ? [
            {
                uid: new Date().getTime(),
                url: newValue,
                status: "success",
                fromItem: "upload-img",
            }
        ] : [];
    } else {
        if (newValue && typeof newValue[0] == "string") {
            fileList.value = newValue.map(item => {
                return {
                    uid: new Date().getTime() + Math.random(),
                    url: item,
                    status: "success",
                    fromItem: "upload-img",
                } as fileInfo;
            })
        } else {
            fileList.value = newValue as fileInfo[];
        }
    }
}, {
    deep: true,
    immediate: true
})
</script>
<style scoped lang="scss">
.upload-img-box {
    display: flex;
    flex-wrap: wrap;

    .show-img-box {
        margin-right: 10px;
    }
}

.avatar-uploader {
    :deep(li) {
        width: v-bind(imgWidth);
        height: v-bind(imgHeight);
    }

    :deep(.el-upload) {
        width: v-bind(imgWidth);
        height: v-bind(imgHeight);
    }

    &.is-disabled {
        :deep(.el-upload) {
            display: none;
        }
    }
}
</style>